package org.tech4j.common.core.sign.extractor;

import com.google.common.collect.ImmutableMap;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.tech4j.common.core.constant.Constants;
import org.tech4j.common.core.sign.api.SignParameters;
import org.tech4j.common.utils.JsonUtils;
import org.tech4j.common.core.request.param.ParamTypeEnum;
import org.tech4j.common.core.request.param.ParameterDataFactory;

import java.net.URI;
import java.util.Map;
import java.util.Objects;

/**
 * @program: tech4j-common
 * @description:
 * @author: YuKai Fan
 * @create: 2025/3/2 21:10
 **/
public class DefaultExtractor implements SignParameterExtractor {
    private static final Map<String, SignParameterExtractor> VERSION_EXTRACTOR =
            ImmutableMap.of(
                    VersionOneExtractor.VERSION_1, new VersionOneExtractor(),
                    VersionTwoExtractor.VERSION_2, new VersionTwoExtractor()
            );

    @Override
    public SignParameters extract(String requestBody) {
        Map<String, String> paramMap = JsonUtils.toStringMap(requestBody);
        if (paramMap == null || paramMap.isEmpty()) {
            return new SignParameters();
        }
        SignParameters signParameters = new SignParameters(
                VersionTwoExtractor.VERSION_2,
                paramMap.get(Constants.APP_KEY),
                paramMap.get(Constants.TIMESTAMP),
                paramMap.get(Constants.SIGN),
                URI.create(paramMap.get(Constants.URI)),
                paramMap.get("alg"));
        paramMap.remove(Constants.SIGN);
        signParameters.setParameters(JsonUtils.toJsonString(paramMap));
        return signParameters;
    }

    @Override
    public SignParameters extract(HttpServletRequest request) {
        return this.extract(request, ParamTypeEnum.HEADER.getType(), Constants.VERSION);
    }

    @Override
    public SignParameters extract(HttpServletRequest request, String paramType, String paramKey) {
        String data = ParameterDataFactory.buildData(paramType, paramKey, request);
        if (StringUtils.isBlank(data)) {
            return SignParameters.ERROR_PARAMETERS;
        }
        SignParameterExtractor extractor = VERSION_EXTRACTOR.get(data);
        if (Objects.isNull(extractor)) {
            return SignParameters.ERROR_PARAMETERS;
        }
        return extractor.extract(request, paramType, paramKey);
    }
}
